import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Config {
    // 2 异常的捕获
    /** 2.1 异常声明throws
     * 注意事项：
     （1）throws必须跟在方法的参数列表之后
     （2）声明的异常必须是Exception或者EXception的子类
     （3）方法内部如果抛出了多个异常，throws之后必须跟多个异常，之间用逗号隔开，如果抛出多个异常类型具有父子关系，直接声明父类
     （4）调用声明抛出异常的方法时，调用者必须对该异常进行处理，或者继续使用throws抛出
     */
    File file;
        /*
        FileNotFoundException：编译时异常，表明文件不存在
        此处不作处理，也没有能力处理，应该将错误信息报告给调用者，让调用者检查文件名字是否给错误了……
         */
    // eg2：加载指定的配置文件config.ini
        /*public void openConfig(String filename) throws FileNotFoundException{
            if(filename.equals("config.ini")){
                throw new FileNotFoundException("配置文件名字不对");
            }
            //打开文件
        }*/

    // eg3 ：throws之后必须跟多个异常
    //public void openConfig(String filename) throws IOException,FileNotFoundException{
    //FileNotFoundException继承自 IOException，所以只需要声明父类
    /*public void openConfig(String filename) throws IOException {
        if(filename.endsWith(".ini")){
            throw new IOException("文件不是.ini文件");
        }
        if(filename.equals("config.ini")){
            throw new FileNotFoundException("配置文件名字不对");
        }
    }

    public void readConfig(){
        //读文件
    }*/

    /** 2.2 try-catch捕获并处理 */
    // eg4 ：读取配置文件，如果配置文件名字不是指定名字，抛出异常，调用者进行异常处理
    public void openConfig(String filename) throws FileNotFoundException{
        if(!filename.equals("config.ini")){
            throw new FileNotFoundException("配置文件名字不对");
        }
        //打开文件
    }
    public void readConfig(){
    }

    /** try-catch的注意事项：
     * （1）try块内抛出异常位置之后的代码将不会被执行
     * （2）如果抛出异常类型与catch异常不匹配，即异常不会被成功捕获，也就不会被处理，继续往外抛，直到JVM收到后中断程序--异常是按照类型来捕获
     * （3）try可能会抛出多个异常对象。则必须用多个catch来捕获--即多种异常，多次捕获
     * （4）如果异常之间有父子关系，一定是子类异常在前catch，父类异常在后catch，否则语法错误
     */
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        try {
            System.out.println("before");
            arr = null;
            System.out.println(arr[100]);
            System.out.println("after");
        }catch (NullPointerException e){ //永远捕获执行到
            e.printStackTrace();
        }catch (Exception e){ //Exception可以捕获所有的异常
            e.printStackTrace();
        }
        System.out.println("after try catch");
    }

    public static void main4(String[] args) {
        int[] arr = {1,2,3};
        try {
            System.out.println("before");
            System.out.println(arr[100]);
            System.out.println("after");
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("这个数字下标越界异常");
            e.printStackTrace();
        }catch (NullPointerException e){
            System.out.println("这是个空指针异常");
            e.printStackTrace();
        }
            System.out.println("after try catch");
    }

    public static void main3(String[] args) {
        try {
            int[] arr = {1,2,3};
            System.out.println(arr[3]); //此处会抛出数组越界异常
        }catch (NullPointerException e){ //捕获时捕获的是空指针异常，真正的异常无法被捕获到
            e.printStackTrace();
        }
        System.out.println("后续代码");
    }

    public static void main2(String[] args) { //eg4
        Config config = new Config();
        try {
            config.openConfig("config.txt");
            System.out.println("文件打开成功");
        }catch (IOException e){
//            System.out.println(e.getMessage()); //只打印异常信息
//            System.out.println(e); //打印异常类型：异常信息
            e.printStackTrace(); //打印信息最全面
        }
        //一旦异常被捕获了处理了，此处的代码会执行
        System.out.println("异常被捕获了处理了，此处的代码会执行");
    }

    //调用声明抛出异常的方法时，调用者必须对该异常进行处理，或者继续使用throws抛出
    public static void main1(String[] args) throws IOException {
        Config config = new Config();
        config.openConfig("config.ini"); //eg2,eg3
    }
}
